package com.starview.star.compiler.canonical;

import java.util.Map.Entry;
import java.util.SortedMap;

import com.starview.platform.data.type.IType;
import com.starview.platform.data.type.Location;
import com.starview.platform.data.type.TypeUtils;
import com.starview.star.compiler.util.PrettyPrintDisplay;

@SuppressWarnings("serial")
public class RecordTerm extends BaseExpression
{
  private final IContentExpression fun;
  private final SortedMap<String, IContentExpression> arguments;

  public RecordTerm(Location loc, IType type, IContentExpression fun, SortedMap<String, IContentExpression> arguments)
  {
    super(loc, type);
    this.fun = fun;
    this.arguments = arguments;
  }

  public RecordTerm(Location loc, IType type, SortedMap<String, IContentExpression> args)
  {
    this(loc, type, new Variable(loc, TypeUtils.constructorType(type, type), TypeUtils.anonRecordLabel(type)), args);
  }

  @Override
  public void prettyPrint(PrettyPrintDisplay disp)
  {
    int mark = disp.markIndent(2);
    if (!isAnonRecord())
      fun.prettyPrint(disp);
    disp.append("{ ");
    String sep = "";
    for (Entry<String, IContentExpression> entry : arguments.entrySet()) {
      disp.append(sep);
      sep = ";\n";

      disp.appendId(entry.getKey());
      disp.append("=");
      entry.getValue().prettyPrint(disp);
    }
    disp.popIndent(mark);
    disp.append("}");
  }

  public boolean isAnonRecord()
  {
    return fun instanceof Variable && TypeUtils.isAnonRecordLabel(((Variable) fun).getName());
  }

  @Override
  public void accept(CanonicalVisitor visitor)
  {
    visitor.visitAggregate(this);
  }

  @Override
  public <A, E, P, C, D, T> E transform(TransformExpression<A, E, P, C, D, T> transform, T context)
  {
    return transform.transformRecord(this, context);
  }

  public IContentExpression getFun()
  {
    return fun;
  }

  public SortedMap<String, IContentExpression> getArguments()
  {
    return arguments;
  }
}
